package com.example.service.iml;

import com.example.bean.DevicePara;
import com.example.bean.NetInfo;
import com.example.bean.RemoteNetInfo;
import com.example.config.FinalConfig;
import com.example.constant.WorkMode;
import com.example.enmu.ResultCodeEnum;
import com.example.listen.TCPServer;
import com.example.mapper.SdInfoMapper;
import com.example.model.SdInfo;
import com.example.model.dto.PageDTO;
import com.example.model.qo.PageResult;
import com.example.result.DataResponse;
import com.example.service.CLibrary;
import com.example.service.DeviceService;
import com.example.service.ITableService;
import com.example.util.ByteUtil;
import com.example.util.IpAddressUtil;
import com.example.util.TypeConversionUtil;
import com.sun.jna.ptr.IntByReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    ITableService tableService;
    @Autowired
    SdInfoMapper sdInfoMapper;

    @Override
    public PageResult pageList(PageDTO pageDTO) {
        String sql="select id, device_name as deviceName, device_type as deviceType,device_model as deviceModel, device_id as deviceId,communication_mode as communicationMode, mac_address as macAddress, ip_address as ipAddress, port, remote_parm as remoteParm, online, status, is_delete as isDelete, create_time, update_time as updateTime from sd_info where is_delete = ? ";
        if(pageDTO.getQueryData()!=null && !"".equals(pageDTO.getQueryData())){
            pageDTO.setQueryData("%"+pageDTO.getQueryData()+"%");
            sql+="and (ip_address like ? or device_name like ?)";
        }
        sql+="order by ip_address asc,id asc";
        return tableService.selectPageBySql(sql, new Object[]{FinalConfig.DELETE_NO,pageDTO.getQueryData(),pageDTO.getQueryData()}, pageDTO.getPageNum(), pageDTO.getPageSize());
    }

    @Override
    public DataResponse updateInfo(SdInfo sdInfo) {
        if(sdInfo.getIpAddress()==null){
            return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"ip地址不能为空！");
        }
        SdInfo databaseInfo = sdInfoMapper.selectSdInfoById(sdInfo.getId());
        if(databaseInfo==null){
            return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"读取设备信息失败！");
        }
        databaseInfo.setIpAddress(sdInfo.getIpAddress());
        int port =databaseInfo.getPort();
        IntByReference hComm = new IntByReference();
        IntByReference intByReference = CLibrary.INSTANCE.OpenNetConnection(hComm, sdInfo.getIpAddress(), port, 2500);
        String data = TypeConversionUtil.typeConversion(intByReference);
        if (data == null && hComm.getValue() != 0) {
            try {
                NetInfo info = new NetInfo();
                CLibrary.INSTANCE.GetNetInfo(hComm.getValue(), info);
                if(!databaseInfo.getMacAddress().equals(ByteUtil.byteToMacAddressString(info.getMAC()))){
                    return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"设备mac和ip地址不符！");
                }
                if (ByteUtil.byteArrayToPort(info.getPORT()) == port) {
                    String mac = ByteUtil.byteToMacAddressString(info.getMAC());
                    SdInfo byId = getDeviceById(databaseInfo.getId());
                    if(mac.equals(databaseInfo.getMacAddress()) && byId!=null && mac.equals(byId.getMacAddress())){
                        RemoteNetInfo remoteNetInfo = new RemoteNetInfo();
                        CLibrary.INSTANCE.GetRemoteNetInfo(hComm.getValue(), remoteNetInfo);
                        databaseInfo.setRemoteParm(ByteUtil.bytesToIP(remoteNetInfo.getIP())+":"+ByteUtil.byteArrayToPort(remoteNetInfo.getPORT()));
                        updateDevice(databaseInfo);
                        closeHcom(hComm);
                        return new DataResponse("操作成功！");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Error e) {
                e.printStackTrace();
            }
        }
        closeHcom(hComm);
        return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"读取设备信息失败！");
    }



    public List<SdInfo>  selectList(SdInfo sdInfo){
        return sdInfoMapper.selectSdInfoList(sdInfo);
    }

    public void  updateDevice(SdInfo sdInfo){
        sdInfo.setUpdateTime(new Date());
        sdInfoMapper.updateSdInfo(sdInfo);
    }

    @Override
    public SdInfo getDeviceById(Long id) {
        return sdInfoMapper.selectSdInfoById(id);
    }

    @Override
    public DataResponse openDevice(SdInfo sdInfo) {
        SdInfo databaseInfo = sdInfoMapper.selectSdInfoById(sdInfo.getId());
        if(databaseInfo==null || databaseInfo.getIpAddress()==null || "".equals(databaseInfo.getMacAddress())){
            return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"读取设备信息失败！");
        }
        IntByReference hComm = new IntByReference();
        IntByReference intByReference = CLibrary.INSTANCE.OpenNetConnection(hComm, databaseInfo.getIpAddress(), databaseInfo.getPort(), 3000);
        String data = TypeConversionUtil.typeConversion(intByReference);
        if (data == null && hComm.getValue() != 0) {
            try {
                DevicePara.ByReference devicePara = new DevicePara.ByReference();
                CLibrary.INSTANCE.GetDevicePara(hComm.getValue(), devicePara);
                int i = TypeConversionUtil.byteToInt(devicePara.WORKMODE);
                if(i== WorkMode.ACTIVE_MODE){
                    if(databaseInfo.getStatus()!=1){
                        databaseInfo.setStatus(1);
                        databaseInfo.setUpdateTime(new Date());
                        updateDevice(databaseInfo);
                    }
                    closeHcom(hComm);
                    return new DataResponse("操作成功！");
                }
                devicePara.setWORKMODE(TypeConversionUtil.intTobyte(WorkMode.ACTIVE_MODE));
                IntByReference reference = CLibrary.INSTANCE.SetDevicePara(hComm.getValue(), devicePara);
                String res = TypeConversionUtil.typeConversion(reference);
                closeHcom(hComm);
                if(res == null){
                    databaseInfo.setStatus(1);
                    databaseInfo.setUpdateTime(new Date());
                    updateDevice(databaseInfo);
                    return new DataResponse("操作成功！");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Error e) {
                e.printStackTrace();
            }
        }
        return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"操作失败！");
    }

    @Override
    public DataResponse closeDevice(SdInfo sdInfo) {
        SdInfo databaseInfo = sdInfoMapper.selectSdInfoById(sdInfo.getId());
        if(databaseInfo==null|| databaseInfo.getIpAddress()==null || "".equals(databaseInfo.getMacAddress())){
            return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"读取设备信息失败！");
        }
        IntByReference hComm = new IntByReference();
        IntByReference intByReference = CLibrary.INSTANCE.OpenNetConnection(hComm, databaseInfo.getIpAddress(), databaseInfo.getPort(), 3300);
        String data = TypeConversionUtil.typeConversion(intByReference);
        if (data == null && hComm.getValue() != 0) {
            try {
                DevicePara.ByReference devicePara = new DevicePara.ByReference();
                CLibrary.INSTANCE.GetDevicePara(hComm.getValue(), devicePara);
                int i = TypeConversionUtil.byteToInt(devicePara.WORKMODE);
                if(i != WorkMode.ACTIVE_MODE){
                    if(databaseInfo.getStatus()!=2){
                        databaseInfo.setStatus(2);
                        databaseInfo.setUpdateTime(new Date());
                        updateDevice(databaseInfo);
                    }
                    closeHcom(hComm);
                    return new DataResponse("操作成功！");
                }
                devicePara.setWORKMODE(TypeConversionUtil.intTobyte(WorkMode.RESPONSE_MODE));
                IntByReference reference = CLibrary.INSTANCE.SetDevicePara(hComm.getValue(), devicePara);
                String res = TypeConversionUtil.typeConversion(reference);
                closeHcom(hComm);
                if(res == null){
                    databaseInfo.setStatus(2);
                    databaseInfo.setUpdateTime(new Date());
                    updateDevice(databaseInfo);
                    return new DataResponse("操作成功！");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Error e) {
                e.printStackTrace();
            }
        }
        return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"操作失败！");
    }

    @Override
    public DataResponse refreshDevice(SdInfo sdInfo) {
        SdInfo databaseInfo = sdInfoMapper.selectSdInfoById(sdInfo.getId());
        if(databaseInfo==null || databaseInfo.getIpAddress()==null || "".equals(databaseInfo.getMacAddress())){
            return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"读取设备信息失败！");
        }
        databaseInfo.setOnline(0);
        databaseInfo.setStatus(2);
        IntByReference hComm = new IntByReference();
        IntByReference intByReference = CLibrary.INSTANCE.OpenNetConnection(hComm, databaseInfo.getIpAddress(), databaseInfo.getPort(), 2500);
        String data = TypeConversionUtil.typeConversion(intByReference);
        if (data == null && hComm.getValue() != 0) {
            try {
                NetInfo info = new NetInfo();
                CLibrary.INSTANCE.GetNetInfo(hComm.getValue(), info);
                if(!databaseInfo.getMacAddress().equals(ByteUtil.byteToMacAddressString(info.getMAC()))){
                    return new DataResponse(ResultCodeEnum.SYSTEM_ERROR,"设备mac和ip地址不符！");
                }
                if (ByteUtil.byteArrayToPort(info.getPORT()) == 8000) {
                    databaseInfo.setOnline(1);
                }
                DevicePara.ByReference devicePara = new DevicePara.ByReference();
                CLibrary.INSTANCE.GetDevicePara(hComm.getValue(), devicePara);
                int i = TypeConversionUtil.byteToInt(devicePara.WORKMODE);
                if(i == WorkMode.ACTIVE_MODE){
                    databaseInfo.setStatus(1);
                }
                RemoteNetInfo remoteNetInfo = new RemoteNetInfo();
                CLibrary.INSTANCE.GetRemoteNetInfo(hComm.getValue(), remoteNetInfo);
                databaseInfo.setRemoteParm(ByteUtil.bytesToIP(remoteNetInfo.getIP())+":"+ByteUtil.byteArrayToPort(remoteNetInfo.getPORT()));
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Error e) {
                e.printStackTrace();

            }
        }
        closeHcom(hComm);
        sdInfoMapper.updateSdInfo(databaseInfo);
        return new DataResponse("刷新成功！");
    }

    @Override
    public void saveCardRecord(String mac,String cardInfo,String fromIp) {
        SdInfo sdInfo = sdInfoMapper.selectSdInfoByMac(mac);
        if(sdInfo!=null){
            String sql="INSERT INTO sd_credit_card_record ( sd_info_id, card_info, device_name, device_type, device_id, mac_address, ip_address, communication_mode, remote_parm, create_time, data_collect_time,device_model) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now(),?);";
            tableService.insertBySql(sql,new Object[]{sdInfo.getId(),cardInfo,sdInfo.getDeviceName(),sdInfo.getDeviceType(),sdInfo.getDeviceId(),mac,fromIp,sdInfo.getCommunicationMode(),sdInfo.getRemoteParm(),sdInfo.getDeviceModel()});
        }else {
            /*String sql="INSERT INTO sd_credit_card_record (card_info, mac_address, ip_address, communication_mode, remote_parm, create_time, data_collect_time) " +
                    "VALUES (?, ?, ?, ?, ?, now(), now());";
            tableService.insertBySql(sql,new Object[]{cardInfo,mac,fromIp,1,IpAddressUtil.getIntranetIpAddress()+":"+ TCPServer.port});*/
        }
    }

    @Override
    public void saveCardRecord(String cardInfo, String fromIp) {
        SdInfo sdInfo = sdInfoMapper.selectSdInfoByIp(fromIp);
        if(sdInfo!=null){
            String sql="INSERT INTO sd_credit_card_record ( sd_info_id, card_info, device_name, device_type, device_id, mac_address, ip_address, communication_mode, remote_parm, create_time, data_collect_time,device_model) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now(),?);";
            tableService.insertBySql(sql,new Object[]{sdInfo.getId(),cardInfo,sdInfo.getDeviceName(),sdInfo.getDeviceType(),sdInfo.getDeviceId(),sdInfo.getMacAddress(),fromIp,sdInfo.getCommunicationMode(),sdInfo.getRemoteParm(),sdInfo.getDeviceModel()});
        }else {
            /*String sql="INSERT INTO sd_credit_card_record (card_info, mac_address, ip_address, communication_mode, remote_parm, create_time, data_collect_time) " +
                    "VALUES (?, ?, ?, ?, ?, now(), now());";
            tableService.insertBySql(sql,new Object[]{cardInfo,mac,fromIp,1,IpAddressUtil.getIntranetIpAddress()+":"+ TCPServer.port});*/
        }
    }

    private void closeHcom(IntByReference hComm) {
        if (hComm.getValue() != 0) {
            try {
                System.out.println("关闭机器");
                CLibrary.INSTANCE.CloseDevice(hComm.getValue());
            } catch (Error e) {
                e.printStackTrace();
            }
        }
    }

}
